﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;


namespace Snake.Client
{
    public class Body
    {
        private readonly List<Segment> _segmentsList;
        private static readonly Random _randomizer = new Random(DateTime.Now.Millisecond);

        public Body(Segment headSegment)
        {
            _segmentsList = new List<Segment> { headSegment };
        }
        public Body()
            : this(new Segment(new Vector2(40, 60), new Vector2(1, 0)))
        {
            Head.Position = new Vector2
            (
                _randomizer.Next(Screen.Width - GameInfo.SegmentSize),
                _randomizer.Next(Screen.Height - GameInfo.SegmentSize)
            );
        }

        public int Size
        {
            get { return _segmentsList.Count; }
        }
        public Segment Head
        {
            get { return _segmentsList.First(); }
            set { _segmentsList[0] = value; }
        }
        public List<Segment> Segments
        {
            get { return _segmentsList; }
        }
        

        public void Move()
        {
            for (var i = Size - 1; i > 0; i--)
            {
                _segmentsList[i].DirectionByPrevious(_segmentsList[i - 1], i);
                _segmentsList[i].Move();
            }

            Head.Move();
        }
        public void Enlarge()
        {
            _segmentsList.Add(new Segment(Head.Position - (Head.Direction * GameInfo.SegmentSize), new Vector2(1, 0)));
        }
        public void Scatter()
        {
            for (var i = 1; i < Size; i++)
            {
                Segments[i].Position = new Vector2
               (
                    _randomizer.Next(Screen.Width - GameInfo.SegmentSize),
                    _randomizer.Next(Screen.Height - GameInfo.SegmentSize)
               );
            }
        }
        public bool SelfCollision()
        {
            for (var i = 2; i < Size; i++)
            {
                if (Head.CollidesWithSegment(_segmentsList[i]))
                {
                    return true;
                }
            }
            return false;
        }
        public bool FoodCollision(Food food)
        {
            Vector2 headFoodPositionDifference = Head.Position - food.Position;
            if (Math.Abs(headFoodPositionDifference.X) < Food.Size && Math.Abs(headFoodPositionDifference.Y) < Food.Size)
            {
                return true;
            }
            return false;
        }
        public bool CollidesWithBody(Body otherBody)
        {
            foreach (var segment in otherBody._segmentsList)
            {
                if (Head.CollidesWithSegment(segment))
                {
                    return true;
                }
            }

            return false;
        }
        public void HeadDirectionByEvent(SnakeEvent snakeEvent)
        {
            Vector2 newDirectionVector = _EventToVector(snakeEvent);

            if (newDirectionVector + Head.Direction != Vector2.Zero)
            {
                Head.Direction = newDirectionVector;
            }
        }

        private static Vector2 _EventToVector(SnakeEvent snakeEvent)
        {
            switch (snakeEvent)
            {
                case SnakeEvent.Right:
                    return new Vector2(1, 0);

                case SnakeEvent.Left:
                    return new Vector2(-1, 0);

                case SnakeEvent.Down:
                    return new Vector2(0, 1);

                case SnakeEvent.Up:
                    return new Vector2(0, -1);

                default:
                    Console.WriteLine("ovo se ne bi tribalo dogodit");
                    throw new Exception("Invalid SnakeEvent");
            }
        }
    }
}